Skip to content

Conversation

@hawkeyeking
Copy link

@hawkeyeking hawkeyeking commented Dec 9, 2025

Add HoloCat application that integrates EtherCAT real-time communication with NVIDIA's Holoscan streaming framework.

Key Features:

  • Real-time EtherCAT master implementation using EC-Master SDK
  • Holoscan operator architecture with periodic scheduling
  • Data flow integration between EtherCAT and Holoscan operators
  • Configurable cycle times and real-time priorities
  • Docker containerization with proper capabilities (in-progress)

Components:

  • HolocatOp: Main EtherCAT operator with state machine management
  • HcDataTxOp: Data transmission operator for counter generation
  • HcDataRxOp: Data reception operator for processing received data

This enables real-time industrial automation applications using EtherCAT fieldbus communication within the Holoscan ecosystem.

Summary by CodeRabbit

  • New Features

    • Added HoloCat application for EtherCAT real-time integration, including runtime operators (data TX/RX and EtherCAT operator), CLI entrypoint, and app wiring.
    • Added configuration (YAML, ENI), metadata, and container image support for easy deployment.
  • Tooling

    • Integrated EC‑Master SDK discovery and a verification script to validate SDK/system prerequisites.
  • Documentation

    • New README with usage, configuration examples, and troubleshooting guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

Add HoloCat application that integrates EtherCAT real-time
communication with NVIDIA's Holoscan streaming framework.

Key Features:
- Real-time EtherCAT master implementation using EC-Master SDK
- Holoscan operator architecture with periodic scheduling
- Data flow integration between EtherCAT and Holoscan operators
- Configurable cycle times and real-time priorities
- Docker containerization with proper capabilities (in-progress)

Components:
- HolocatOp: Main EtherCAT operator with state machine management
- HcDataTxOp: Data transmission operator for counter generation
- HcDataRxOp: Data reception operator for processing received data
- Comprehensive configuration system with validation
- Build system integration with CMake and Docker

This enables real-time industrial automation applications using
EtherCAT fieldbus communication within the Holoscan ecosystem.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 9, 2025

Walkthrough

Adds a new "holocat" application providing EtherCAT real-time integration: build and CMake find support for EC‑Master SDK, Docker packaging and verification, configuration files (YAML/ENI), Holoscan operators and application wiring, and metadata/README.

Changes

Cohort / File(s) Summary
Top-level registration & app CMake
applications/CMakeLists.txt, applications/holocat/CMakeLists.txt, applications/holocat/cpp/CMakeLists.txt
Registers the holocat app, requires CMake ≥3.20, adds FindEcMaster usage, and configures the holocat C++ target with include/link settings, compile flags, RPATH, and optional setcap POST_BUILD.
CMake find module
applications/holocat/FindEcMaster.cmake
New find module to locate EC‑Master SDK (headers, libraries), expose variables/targets (EcMaster::EcMaster, ECMASTER_*), extract version, and use FindPackageHandleStandardArgs.
Docker & verification
applications/holocat/Dockerfile, applications/holocat/scripts/verify_ecmaster.sh
New Dockerfile to package EC‑Master SDK and runtime dependencies, create holocat user, set env vars and default CMD; verification script checks EC‑Master layout, lib presence, link layers, and toolchain availability.
Docs & metadata
applications/holocat/README.md, applications/holocat/metadata.json
Adds README with usage/prereqs and metadata.json describing app, authors, versions, platforms, modes, and runtime/build requirements.
Configurations
applications/holocat/configs/holocat_config.yaml, applications/holocat/configs/eni2.xml
Adds holocat YAML config (adapter, eni_file, cycle_time_us, RT priorities, DIO offsets, flags) and an ENI XML describing EtherCAT master/slaves, PDO mappings, and init sequence.
Application entry & CLI
applications/holocat/cpp/main.cpp
New main with CLI parsing (-c/--config, --print-config, -h), config file resolution/validation, logging init, and app run/exception handling.
Application & validation
applications/holocat/cpp/holocat_app.hpp, applications/holocat/cpp/holocat_app.cpp
New HolocatApp class that composes operators, extracts and validates HolocatConfig (adapter, ENI path, cycle_time_us, priorities, defaults), and throws on invalid config.
EtherCAT operator core
applications/holocat/cpp/holocat_op.hpp, applications/holocat/cpp/holocat_op.cpp
New HolocatOp operator: HolocatConfig struct, async bus startup state machine, EC‑Master parameter initialization, ConfigureNetwork, lifecycle hooks (setup/start/compute/stop), job thread entry, process image I/O, and LogWrapper mapping EC‑Master logs.
Data operators (TX/RX)
applications/holocat/cpp/hc_data_tx_op.hpp, applications/holocat/cpp/hc_data_tx_op.cpp, applications/holocat/cpp/hc_data_rx_op.hpp, applications/holocat/cpp/hc_data_rx_op.cpp
New simple Holoscan operators: HcDataTxOp emits a wrapping counter; HcDataRxOp receives an int, stores last_count_, and logs receipts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • tbirdso
  • NigelNelson
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(holocat): Add EtherCAT application' accurately and concisely summarizes the main change—introducing a new HoloCat application with EtherCAT integration into the HoloHub repository.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4cc9b7b and f1ecb65.

📒 Files selected for processing (1)
  • applications/CMakeLists.txt
🚧 Files skipped from review as they are similar to previous changes (1)
  • applications/CMakeLists.txt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🧹 Nitpick comments (15)
applications/holocat/README.md (1)

26-26: Replace hardcoded path with placeholder.

The ECMASTER_ROOT path is user-specific and should use a placeholder instead.

Apply this diff:

-export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm
+export ECMASTER_ROOT=/path/to/ec-master-sdk
applications/holocat/cpp/hc_data_rx_op.hpp (1)

19-20: Clarify data source in documentation.

The documentation states the operator "receives integer data from the ECat bus," but based on the operator architecture, it actually receives data from another Holoscan operator (HolocatOp). Consider clarifying the data flow.

Example:

- * A Holoscan operator that receives integer data from the ECat bus.
- * This operator acts as a data receiver, receiving integer values from the ECat bus.
+ * A Holoscan operator that receives integer data from the HolocatOp.
+ * This operator acts as a data receiver in the Holocat data flow pipeline.
applications/holocat/configs/holocat_config.yaml (2)

5-5: Use generic adapter name in example configuration.

The adapter name appears to be a specific hardware MAC-based identifier. For an example configuration file, use a more generic placeholder.

Apply this diff:

-  adapter_name: "enxc84bd6d2788c"
+  adapter_name: "eth0"  # Change to your EtherCAT interface

Note: This matches the placeholder used in the README example.


9-9: Replace hardcoded path with relative or placeholder path.

The ENI file path contains a user-specific absolute path. Use a relative path or generic placeholder.

Apply this diff:

-  eni_file: "/home/hking/devel/holo/holohub/applications/holocat/configs/eni2.xml"
+  eni_file: "applications/holocat/configs/eni2.xml"

Or use an environment variable placeholder as suggested in the comment above.

applications/holocat/CMakeLists.txt (1)

1-30: Add testing section for functional tests.

Per coding guidelines, applications should include a testing section in CMakeLists.txt for functional testing using CTest.

As per coding guidelines, applications should include testing.

Consider adding after the add_subdirectory(cpp) line:

# Testing
if(BUILD_TESTING)
    add_subdirectory(tests)
endif()
applications/holocat/configs/eni2.xml (1)

1-1: Document the example ENI configuration.

This ENI file appears to be for specific hardware (simco drive 40028083-00-0 and WAGO 750-354). Consider adding a comment or separate README in the configs directory explaining that this is an example configuration and users must generate their own ENI file for their specific EtherCAT hardware setup.

Consider adding applications/holocat/configs/README.md:

# EtherCAT Configuration Files

## eni2.xml

This is an example EtherCAT Network Information (ENI) file for:
- SubDevice_1001: simco drive 40028083-00-0
- SubDevice_1002: WAGO 750-354 I/O module

**Important**: You must generate your own ENI file matching your specific EtherCAT hardware configuration using EtherCAT configuration tools (e.g., TwinCAT, EC-Engineer, or acontis EC-Engineer).
applications/holocat/cpp/CMakeLists.txt (1)

1-89: Missing CTest integration for functional testing.

Per coding guidelines, applications should include a testing section in CMakeLists.txt for functional testing using CTest.

Consider adding a testing section:

# Testing
if(BUILD_TESTING)
    enable_testing()
    # Add test cases here
endif()
applications/holocat/cpp/hc_data_tx_op.cpp (1)

28-30: Counter starts at 1, not 0.

The counter increments before use, so the first emitted value is 1, not 0. If starting at 0 is intended, consider swapping the order:

-  // Increment counter
-  counter_++;
-  counter_ = counter_ % kMaxCount;
-
   // Emit current counter value
   op_output.emit<int>(counter_, "count_out");
+
+  // Increment counter for next cycle
+  counter_ = (counter_ + 1) % kMaxCount;
applications/holocat/cpp/hc_data_rx_op.cpp (1)

33-34: INFO-level logging on every cycle may be excessive.

In a real-time system with fast cycle times, logging at INFO level on every received value will flood logs and potentially impact performance. Consider using DEBUG level similar to HcDataTxOp.

   last_count_ = maybe_count.value();
-  HOLOSCAN_LOG_INFO("HcDataRxOp: Received count: {}", last_count_);
+  // Log periodically to avoid spam
+  if (last_count_ % 50 == 0) {
+    HOLOSCAN_LOG_DEBUG("HcDataRxOp: 50x Received count = {}", last_count_);
+  }
applications/holocat/cpp/holocat_op.cpp (3)

175-182: Blocking sleep(1) in stop() delays shutdown.

Using sleep(1) blocks the calling thread unconditionally. Consider using a non-blocking approach or reducing the delay if waiting for async completion.

     pending_state_transition_ = std::async(std::launch::async, [this]() {
         return ecatSetMasterState(kEthercatStateChangeTimeout_, eEcatState_INIT);
     });
 
-    sleep(1);
+    // Wait for state transition to complete with timeout
+    if (pending_state_transition_.wait_for(std::chrono::seconds(5)) == std::future_status::timeout) {
+        HOLOSCAN_LOG_WARN("State transition to INIT timed out during stop");
+    }
+
     // deinitialize master
     ecatDeinitMaster();

350-364: Static local variable in compute() is not thread-safe.

The static struct timespec t_last is shared across all invocations. If multiple HolocatOp instances run concurrently or the operator is restarted, timing calculations will be incorrect.

Consider making t_last a member variable initialized in start():

+// In class declaration (holocat_op.hpp):
+  struct timespec t_last_{};
+
+// In start():
+  clock_gettime(CLOCK_MONOTONIC, &t_last_);
+
 // In compute():
     struct timespec t_now;
     clock_gettime(CLOCK_MONOTONIC, &t_now);     
-    static struct timespec t_last{t_now.tv_sec, t_now.tv_nsec};
     ...
-    t_last = t_now;
+    t_last_ = t_now;

311-347: EtherCAT job results are silently discarded.

The return values from ecatExecJob calls are assigned to dwRes but then immediately suppressed with EC_UNREFPARM. While this may be intentional for polling mode, consider logging errors at DEBUG level to aid troubleshooting.

     dwRes = ecatExecJob(eUsrJob_ProcessAllRxFrames, EC_NULL);
-    EC_UNREFPARM(dwRes);
+    if (dwRes != EC_E_NOERROR) {
+        HOLOSCAN_LOG_DEBUG("ProcessAllRxFrames returned: {} (0x{:x})", ecatGetText(dwRes), dwRes);
+    }
applications/holocat/cpp/holocat_app.cpp (2)

72-78: Clarify comment about uninitialized values.

The comment "target remains uninitialized" is misleading since HolocatConfig config = {} value-initializes all members (empty strings, zeros, false). The behavior is correct but the comment should reflect the actual semantics.

   auto try_extract = [this](const std::string& key, auto& target) {
     try {
       target = from_config(key).as<std::decay_t<decltype(target)>>();
     } catch (...) {
-      // Key not found or conversion failed - target remains uninitialized
+      // Key not found or conversion failed - target retains default value
     }
   };

42-47: Consider making the counter update period configurable.

The 100ms period for HcDataTxOp is hardcoded. For flexibility, consider adding this as a configuration parameter similar to cycle_time_us.

applications/holocat/cpp/holocat_op.hpp (1)

10-11: Consider using conventional include guard naming.

The include guard INC_HOLOCAT_H with value 1 is unconventional. A more standard pattern would match the filename.

-#ifndef INC_HOLOCAT_H
-#define INC_HOLOCAT_H 1
+#ifndef HOLOCAT_OP_HPP
+#define HOLOCAT_OP_HPP

And update the closing guard:

-#endif /* INC_HOLOCAT_H */
+#endif  // HOLOCAT_OP_HPP
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42a23cd and 4cc9b7b.

📒 Files selected for processing (19)
  • applications/CMakeLists.txt (1 hunks)
  • applications/holocat/CMakeLists.txt (1 hunks)
  • applications/holocat/Dockerfile (1 hunks)
  • applications/holocat/FindEcMaster.cmake (1 hunks)
  • applications/holocat/README.md (1 hunks)
  • applications/holocat/configs/eni2.xml (1 hunks)
  • applications/holocat/configs/holocat_config.yaml (1 hunks)
  • applications/holocat/cpp/CMakeLists.txt (1 hunks)
  • applications/holocat/cpp/hc_data_rx_op.cpp (1 hunks)
  • applications/holocat/cpp/hc_data_rx_op.hpp (1 hunks)
  • applications/holocat/cpp/hc_data_tx_op.cpp (1 hunks)
  • applications/holocat/cpp/hc_data_tx_op.hpp (1 hunks)
  • applications/holocat/cpp/holocat_app.cpp (1 hunks)
  • applications/holocat/cpp/holocat_app.hpp (1 hunks)
  • applications/holocat/cpp/holocat_op.cpp (1 hunks)
  • applications/holocat/cpp/holocat_op.hpp (1 hunks)
  • applications/holocat/cpp/main.cpp (1 hunks)
  • applications/holocat/metadata.json (1 hunks)
  • applications/holocat/scripts/verify_ecmaster.sh (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
{operators,applications,workflows,gxf_extensions}/**/*.{py,cpp,hpp}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

{operators,applications,workflows,gxf_extensions}/**/*.{py,cpp,hpp}: All code must adhere to Holoscan SDK coding standards including proper error handling and validation
Use descriptive English naming for functions, variables, and components; minimize acronyms and brand names
Include inline comments for complex logic in code

Files:

  • applications/holocat/cpp/hc_data_rx_op.hpp
  • applications/holocat/cpp/hc_data_tx_op.hpp
  • applications/holocat/cpp/main.cpp
  • applications/holocat/cpp/holocat_op.cpp
  • applications/holocat/cpp/holocat_op.hpp
  • applications/holocat/cpp/holocat_app.cpp
  • applications/holocat/cpp/hc_data_tx_op.cpp
  • applications/holocat/cpp/hc_data_rx_op.cpp
  • applications/holocat/cpp/holocat_app.hpp
{operators,applications,workflows,gxf_extensions}/**/*.{py,cpp,hpp,cmake}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

All code must compile and build successfully on target platforms before submission

Files:

  • applications/holocat/cpp/hc_data_rx_op.hpp
  • applications/holocat/cpp/hc_data_tx_op.hpp
  • applications/holocat/cpp/main.cpp
  • applications/holocat/cpp/holocat_op.cpp
  • applications/holocat/cpp/holocat_op.hpp
  • applications/holocat/cpp/holocat_app.cpp
  • applications/holocat/cpp/hc_data_tx_op.cpp
  • applications/holocat/cpp/hc_data_rx_op.cpp
  • applications/holocat/cpp/holocat_app.hpp
  • applications/holocat/FindEcMaster.cmake
{operators,applications,workflows,gxf_extensions,tutorials}/**/README.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

README.md must include purpose, usage instructions, requirements, examples, and architecture overview

Files:

  • applications/holocat/README.md
**/*.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use Holoscan SDK glossary terms when referring to HoloHub-specific locations in documentation

Files:

  • applications/holocat/README.md
**/metadata.json

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

When reviewing PRs that modify or add metadata.json files, verify that the category (first tag in the tags array) matches one of the approved categories: Benchmarking, Camera, Computer Vision and Perception, Converter, Deployment, Development, Extended Reality, Healthcare AI, Image Processing, Inference, Interoperability, Medical Imaging, Natural Language and Conversational AI, Networking and Distributed Computing, Optimization, Quantum Computing, Rendering, Robotics, Scheduler, Signal Processing, Streaming, Threading, Video, Video Capture, Visualization, XR

**/metadata.json: Use interface or specific metadata schema for defining contribution structure (metadata.json)
metadata.json must include name, authors, language, version, changelog, holoscan_sdk info, platforms, tags, ranking, dependencies, and run command
metadata.json ranking levels must be self-assessed from 0 (production-ready) to 5 (deprecated) with corresponding requirements
Dependencies must be correctly specified in metadata.json dependencies section

Files:

  • applications/holocat/metadata.json
{applications,workflows}/**/CMakeLists.txt

📄 CodeRabbit inference engine (CONTRIBUTING.md)

CMakeLists.txt must include build system integration using add_holohub_application() for applications and workflows

Files:

  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
  • applications/holocat/cpp/CMakeLists.txt
applications/**/CMakeLists.txt

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Applications should include a testing section in CMakeLists.txt for functional testing using CTest

Files:

  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
  • applications/holocat/cpp/CMakeLists.txt
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to operators/**/CMakeLists.txt : CMakeLists.txt must include build system integration using add_holohub_operator() for operators
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to {applications,workflows}/**/CMakeLists.txt : CMakeLists.txt must include build system integration using add_holohub_application() for applications and workflows
Learnt from: cdinea
Repo: nvidia-holoscan/holohub PR: 1170
File: operators/video_streaming/streaming_client_enhanced/python/CMakeLists.txt:16-24
Timestamp: 2025-10-22T16:53:45.393Z
Learning: The pybind11_add_holohub_module CMake macro in cmake/pybind11_add_holohub_module.cmake encapsulates all pybind11 setup internally, including finding pybind11, linking against holoscan::pybind11 conditionally, and linking the C++ operator target. Operator Python bindings in holohub should only call this macro without additional pybind11 setup.
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to operators/**/CMakeLists.txt : CMakeLists.txt must include build system integration using add_holohub_operator() for operators

Applied to files:

  • applications/holocat/cpp/hc_data_rx_op.hpp
  • applications/holocat/cpp/hc_data_tx_op.hpp
  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
  • applications/holocat/cpp/holocat_op.hpp
  • applications/holocat/cpp/hc_data_tx_op.cpp
  • applications/holocat/cpp/hc_data_rx_op.cpp
  • applications/holocat/cpp/CMakeLists.txt
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to {operators,applications,workflows,gxf_extensions}/**/*.{py,cpp,hpp} : All code must adhere to Holoscan SDK coding standards including proper error handling and validation

Applied to files:

  • applications/holocat/cpp/hc_data_rx_op.hpp
  • applications/holocat/cpp/holocat_op.hpp
  • applications/holocat/cpp/holocat_app.cpp
  • applications/holocat/cpp/hc_data_rx_op.cpp
📚 Learning: 2025-11-24T16:28:06.281Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.281Z
Learning: Applies to **/metadata.json : metadata.json must include name, authors, language, version, changelog, holoscan_sdk info, platforms, tags, ranking, dependencies, and run command

Applied to files:

  • applications/holocat/metadata.json
📚 Learning: 2025-11-24T16:27:43.600Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T16:27:43.600Z
Learning: Applies to **/metadata.json : When reviewing PRs that modify or add `metadata.json` files, verify that the **category** (first tag in the `tags` array) matches one of the approved categories: Benchmarking, Camera, Computer Vision and Perception, Converter, Deployment, Development, Extended Reality, Healthcare AI, Image Processing, Inference, Interoperability, Medical Imaging, Natural Language and Conversational AI, Networking and Distributed Computing, Optimization, Quantum Computing, Rendering, Robotics, Scheduler, Signal Processing, Streaming, Threading, Video, Video Capture, Visualization, XR

Applied to files:

  • applications/holocat/metadata.json
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to {applications,workflows}/**/CMakeLists.txt : CMakeLists.txt must include build system integration using add_holohub_application() for applications and workflows

Applied to files:

  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
  • applications/holocat/cpp/CMakeLists.txt
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to gxf_extensions/**/CMakeLists.txt : CMakeLists.txt must include build system integration using add_holohub_extension() for GXF extensions

Applied to files:

  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
  • applications/holocat/cpp/CMakeLists.txt
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to applications/**/CMakeLists.txt : Applications should include a testing section in CMakeLists.txt for functional testing using CTest

Applied to files:

  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
📚 Learning: 2025-11-24T16:28:06.281Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.281Z
Learning: Applies to applications/**/ : Applications should follow the directory structure with metadata.json, README.md, implementation files, and CMakeLists.txt

Applied to files:

  • applications/holocat/CMakeLists.txt
  • applications/CMakeLists.txt
📚 Learning: 2025-10-22T16:53:45.393Z
Learnt from: cdinea
Repo: nvidia-holoscan/holohub PR: 1170
File: operators/video_streaming/streaming_client_enhanced/python/CMakeLists.txt:16-24
Timestamp: 2025-10-22T16:53:45.393Z
Learning: The pybind11_add_holohub_module CMake macro in cmake/pybind11_add_holohub_module.cmake encapsulates all pybind11 setup internally, including finding pybind11, linking against holoscan::pybind11 conditionally, and linking the C++ operator target. Operator Python bindings in holohub should only call this macro without additional pybind11 setup.

Applied to files:

  • applications/CMakeLists.txt
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Each operator should have at least one associated application demonstrating its capabilities

Applied to files:

  • applications/CMakeLists.txt
📚 Learning: 2025-11-24T16:28:06.280Z
Learnt from: CR
Repo: nvidia-holoscan/holohub PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T16:28:06.280Z
Learning: Applies to operators/**/*.{py,cpp,hpp} : Use TitleCase + 'Op' suffix for operator class names

Applied to files:

  • applications/holocat/cpp/holocat_op.hpp
🧬 Code graph analysis (3)
applications/holocat/cpp/hc_data_rx_op.hpp (2)
applications/holocat/cpp/hc_data_tx_op.hpp (2)
  • spec (40-40)
  • op_input (48-50)
applications/holocat/cpp/holocat_op.hpp (2)
  • spec (63-63)
  • op_input (65-67)
applications/holocat/cpp/hc_data_tx_op.hpp (2)
applications/holocat/cpp/hc_data_rx_op.hpp (2)
  • spec (38-38)
  • op_input (46-48)
applications/holocat/cpp/holocat_op.hpp (2)
  • spec (63-63)
  • op_input (65-67)
applications/holocat/cpp/holocat_op.hpp (3)
applications/holocat/cpp/holocat_app.hpp (1)
  • config (25-25)
applications/holocat/cpp/hc_data_rx_op.hpp (2)
  • spec (38-38)
  • op_input (46-48)
applications/holocat/cpp/hc_data_tx_op.hpp (2)
  • spec (40-40)
  • op_input (48-50)
🪛 Cppcheck (2.18.0)
applications/holocat/cpp/main.cpp

[error] 55-55: There is an unknown macro here somewhere. Configuration is required. If HOLOSCAN_OPERATOR_FORWARD_ARGS is a macro then please configure it.

(unknownMacro)

applications/holocat/cpp/holocat_op.cpp

[error] 55-55: There is an unknown macro here somewhere. Configuration is required. If HOLOSCAN_OPERATOR_FORWARD_ARGS is a macro then please configure it.

(unknownMacro)

applications/holocat/cpp/holocat_app.cpp

[error] 55-55: There is an unknown macro here somewhere. Configuration is required. If HOLOSCAN_OPERATOR_FORWARD_ARGS is a macro then please configure it.

(unknownMacro)

🔇 Additional comments (14)
applications/CMakeLists.txt (1)

152-152: LGTM!

The holocat application is correctly integrated using add_holohub_application() and positioned in proper alphabetical order.

As per coding guidelines, CMakeLists.txt correctly uses add_holohub_application().

applications/holocat/cpp/holocat_app.hpp (1)

1-28: LGTM!

The application class is properly structured, inheriting from holoscan::Application with appropriate method declarations for configuration extraction and validation.

applications/holocat/cpp/hc_data_tx_op.cpp (1)

17-22: LGTM!

The setup method correctly configures the output port with appropriate logging.

applications/holocat/scripts/verify_ecmaster.sh (1)

1-221: Well-structured verification script.

Comprehensive SDK validation covering directory structure, libraries, version extraction, and system requirements. The colored output and clear next steps guidance are helpful.

applications/holocat/cpp/main.cpp (1)

54-74: LGTM!

Clean argument parsing with proper error handling for missing values and unknown options.

applications/holocat/cpp/holocat_op.cpp (1)

32-59: LGTM!

The logging bridge correctly maps EC-Master severity levels to Holoscan logging with appropriate prefixing.

applications/holocat/Dockerfile (2)

29-31: User permissions are appropriately configured.

The holocat user creation with scoped NOPASSWD access for setcap is appropriate for granting real-time capabilities to the application without requiring full root access during normal operation.


45-49: Verification fallback logic is sensible.

The approach of running the full verification script with a fallback to minimal SDK checks (header and library existence) provides build resilience while still ensuring essential components are present.

applications/holocat/FindEcMaster.cmake (2)

123-137: Imported target is correctly defined.

The EcMaster::EcMaster imported target follows CMake conventions with proper interface properties for include directories and link libraries.


1-16: Well-structured CMake find module.

Good use of policy handling for CMP0144 (environment variable handling) and clear documentation of the module's outputs.

applications/holocat/cpp/holocat_app.cpp (1)

140-154: Priority validation handles defaults correctly.

The validation properly detects zero-initialized priorities (from missing config) and applies sensible defaults with appropriate warning logs.

applications/holocat/cpp/holocat_op.hpp (3)

24-38: Configuration struct is well-organized.

The HolocatConfig struct clearly groups related configuration parameters. Including error_message for validation feedback is a pragmatic approach.


53-68: Operator class follows Holoscan conventions.

The HolocatOp class correctly derives from holoscan::Operator, uses the HOLOSCAN_OPERATOR_FORWARD_ARGS macro for constructor forwarding, and follows the TitleCase + 'Op' naming convention per coding guidelines.


105-118: Async state transition design is appropriate for real-time operation.

Using std::future for pending state transitions allows the operator to maintain real-time scheduling while managing the EtherCAT state machine asynchronously.

Comment on lines +26 to +30
message(FATAL_ERROR "EC-Master SDK not found")

# Exit with failure
exit(1)
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove invalid exit() command.

exit(1) is not a valid CMake command. The message(FATAL_ERROR ...) on line 26 already halts CMake configuration, making line 29 unreachable and incorrect.

Apply this diff:

 else()
     message(FATAL_ERROR "EC-Master SDK not found")
-
-    # Exit with failure
-    exit(1)
 endif()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
message(FATAL_ERROR "EC-Master SDK not found")
# Exit with failure
exit(1)
endif()
else()
message(FATAL_ERROR "EC-Master SDK not found")
endif()
🤖 Prompt for AI Agents
In applications/holocat/CMakeLists.txt around lines 26 to 30, remove the invalid
exit(1) call since CMake does not have exit() and message(FATAL_ERROR "EC-Master
SDK not found") already stops configuration; simply delete the exit(1) line so
the FATAL_ERROR stands alone and there is no unreachable/incorrect command.

Comment on lines +47 to +48
# Create executable
add_executable(holocat ${HOLOCAT_SOURCES} ${HOLOCAT_HEADERS})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Missing add_holohub_application() build system integration.

Per HoloHub coding guidelines, applications must use add_holohub_application() for proper build system integration instead of raw add_executable(). This ensures consistent build behavior and integration with the HoloHub infrastructure.

Based on learnings, the CMakeLists.txt should include build system integration using add_holohub_application().

🤖 Prompt for AI Agents
In applications/holocat/cpp/CMakeLists.txt around lines 47-48, the build
currently calls add_executable(holocat ${HOLOCAT_SOURCES} ${HOLOCAT_HEADERS})
which violates HoloHub guidelines; replace this raw add_executable call with the
prescribed add_holohub_application() invocation, passing the same target name
and source/header lists (and any required properties or options the HoloHub
macro expects) so the holocat target is registered through the HoloHub build
integration rather than created directly.

Comment on lines +83 to +89
option(HOLOCAT_SET_CAPABILITIES "Set Linux capabilities during build" ON)
if(HOLOCAT_SET_CAPABILITIES)
add_custom_command(TARGET holocat POST_BUILD
COMMAND sudo setcap 'cap_net_raw,cap_sys_nice,cap_ipc_lock=ep' $<TARGET_FILE:holocat>
COMMENT "Setting capabilities for real-time EtherCAT operation"
)
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

sudo in POST_BUILD will break non-privileged builds.

Using sudo in a CMake post-build command requires interactive authentication and will fail in CI/CD pipelines, containers without sudo, or when users lack sudo access. Consider making this a separate script or installation step rather than part of the build.

-option(HOLOCAT_SET_CAPABILITIES "Set Linux capabilities during build" ON)
+option(HOLOCAT_SET_CAPABILITIES "Set Linux capabilities during build" OFF)
 if(HOLOCAT_SET_CAPABILITIES)
+    message(WARNING "HOLOCAT_SET_CAPABILITIES requires sudo privileges - ensure you have appropriate access")
     add_custom_command(TARGET holocat POST_BUILD
         COMMAND sudo setcap 'cap_net_raw,cap_sys_nice,cap_ipc_lock=ep' $<TARGET_FILE:holocat>
         COMMENT "Setting capabilities for real-time EtherCAT operation"
     )
 endif()

Alternatively, provide a separate install script that users can run manually with appropriate privileges.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
option(HOLOCAT_SET_CAPABILITIES "Set Linux capabilities during build" ON)
if(HOLOCAT_SET_CAPABILITIES)
add_custom_command(TARGET holocat POST_BUILD
COMMAND sudo setcap 'cap_net_raw,cap_sys_nice,cap_ipc_lock=ep' $<TARGET_FILE:holocat>
COMMENT "Setting capabilities for real-time EtherCAT operation"
)
endif()
option(HOLOCAT_SET_CAPABILITIES "Set Linux capabilities during build" OFF)
if(HOLOCAT_SET_CAPABILITIES)
message(WARNING "HOLOCAT_SET_CAPABILITIES requires sudo privileges - ensure you have appropriate access")
add_custom_command(TARGET holocat POST_BUILD
COMMAND sudo setcap 'cap_net_raw,cap_sys_nice,cap_ipc_lock=ep' $<TARGET_FILE:holocat>
COMMENT "Setting capabilities for real-time EtherCAT operation"
)
endif()
🤖 Prompt for AI Agents
In applications/holocat/cpp/CMakeLists.txt around lines 83-89, remove the use of
sudo in the POST_BUILD add_custom_command (it breaks non-privileged/CI builds)
and instead move capability-setting out of the build phase: implement either (a)
an install-time step (e.g. add a CMake install(CODE) or install script that runs
setcap) or (b) a separate optional install target/script (e.g.
add_custom_target(setcap INSTALL_COMMAND ...) or a packaged script in CMake
config) and document that it must be run with appropriate privileges; ensure the
build does not require sudo, optionally add a CMake option to enable automatic
install-time setcap and emit a clear message when capabilities are not set so
users know to run the privileged script.

Comment on lines +1 to +7
/*-----------------------------------------------------------------------------
* hc_data_rx_op.cpp
* HoloCat Data Receive Operator
*
* This file implements the HcDataTxOp operator that generates incrementing
* counter data for testing and demonstration purposes.
*---------------------------------------------------------------------------*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Copy-paste error in file header comment.

The header describes HcDataTxOp but this file implements HcDataRxOp.

 /*-----------------------------------------------------------------------------
  * hc_data_rx_op.cpp
  * HoloCat Data Receive Operator
  * 
- * This file implements the HcDataTxOp operator that generates incrementing
- * counter data for testing and demonstration purposes.
+ * This file implements the HcDataRxOp operator that receives counter
+ * data from the EtherCAT bus for testing and demonstration purposes.
  *---------------------------------------------------------------------------*/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/*-----------------------------------------------------------------------------
* hc_data_rx_op.cpp
* HoloCat Data Receive Operator
*
* This file implements the HcDataTxOp operator that generates incrementing
* counter data for testing and demonstration purposes.
*---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
* hc_data_rx_op.cpp
* HoloCat Data Receive Operator
*
* This file implements the HcDataRxOp operator that receives counter
* data from the EtherCAT bus for testing and demonstration purposes.
*---------------------------------------------------------------------------*/
🤖 Prompt for AI Agents
In applications/holocat/cpp/hc_data_rx_op.cpp around lines 1 to 7, the file
header comment incorrectly references HcDataTxOp and describes transmitter
behavior; update the header to correctly name HcDataRxOp and describe that this
file implements the HcDataRxOp (the data receive operator) and its purpose
(e.g., receiving/parsing incoming data for HoloCat), ensuring the header text
accurately reflects the implementation and purpose.


/**
* @brief Compute method called on each execution cycle
* @param op_input Input context (unused for this source operator)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix incorrect comment about operator type.

The comment states "unused for this source operator" but HcDataRxOp is a receiver/sink operator, not a source operator.

Apply this diff:

-   * @param op_input Input context (unused for this source operator)
+   * @param op_input Input context for receiving counter data
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* @param op_input Input context (unused for this source operator)
* @param op_input Input context for receiving counter data
🤖 Prompt for AI Agents
In applications/holocat/cpp/hc_data_rx_op.hpp around line 42, the param comment
incorrectly refers to HcDataRxOp as a "source operator"; this operator is a
receiver/sink. Update the comment text for the op_input parameter to reflect the
correct operator type (for example: "op_input Input context (unused for this
receiver/sink operator)" or "unused for this sink operator") so the docstring
accurately describes HcDataRxOp.

Comment on lines +100 to +102
if(ECMASTER_VERSION_MAJOR AND ECMASTER_VERSION_MINOR AND ECMASTER_VERSION_PATCH)
set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
endif()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Version string may include empty component if BUILD is not found.

If EC_VERSION_BUILD is not defined in the header, ECMASTER_VERSION_BUILD will be empty, resulting in a version string like "3.2.1." with a trailing dot.

Consider conditionally including the build number:

         if(ECMASTER_VERSION_MAJOR AND ECMASTER_VERSION_MINOR AND ECMASTER_VERSION_PATCH)
-            set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
+            if(ECMASTER_VERSION_BUILD)
+                set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
+            else()
+                set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}")
+            endif()
         endif()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(ECMASTER_VERSION_MAJOR AND ECMASTER_VERSION_MINOR AND ECMASTER_VERSION_PATCH)
set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
endif()
if(ECMASTER_VERSION_MAJOR AND ECMASTER_VERSION_MINOR AND ECMASTER_VERSION_PATCH)
if(ECMASTER_VERSION_BUILD)
set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
else()
set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}")
endif()
endif()
🤖 Prompt for AI Agents
In applications/holocat/FindEcMaster.cmake around lines 100-102, the version
string unconditionally appends ECMASTER_VERSION_BUILD which can be empty and
yield a trailing dot; change the logic to build a base version from
ECMASTER_VERSION_MAJOR.MINOR.PATCH and then only append
".${ECMASTER_VERSION_BUILD}" if ECMASTER_VERSION_BUILD is defined and not empty
(e.g., check using IF(DEFINED ECMASTER_VERSION_BUILD AND NOT
"${ECMASTER_VERSION_BUILD}" STREQUAL "") or similar) so the final
ECMASTER_VERSION has no trailing dot when build is missing.

Comment on lines +25 to +27
"tags": [
"EtherCAT"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Invalid category tag - use approved category.

The first tag in the tags array serves as the category and must be from the approved list. "EtherCAT" is not an approved category. Based on the application's purpose, consider using "Interoperability" or "Networking and Distributed Computing".

As per coding guidelines, the category must match one of the approved categories.

Apply this diff to use an appropriate category:

 		"tags": [
-			"EtherCAT"
+			"Interoperability",
+			"EtherCAT"
 		],

Or if networking focus is more appropriate:

 		"tags": [
-			"EtherCAT"
+			"Networking and Distributed Computing",
+			"EtherCAT"
 		],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"tags": [
"EtherCAT"
],
"tags": [
"Interoperability",
"EtherCAT"
],
Suggested change
"tags": [
"EtherCAT"
],
"tags": [
"Networking and Distributed Computing",
"EtherCAT"
],
🤖 Prompt for AI Agents
In applications/holocat/metadata.json around lines 25 to 27, the first element
of the "tags" array ("EtherCAT") is not an approved category; replace it with an
approved category that reflects the app purpose — e.g. change the first tag to
"Interoperability" (or "Networking and Distributed Computing" if networking is
more accurate) so the tags[0] matches the approved category list and keep any
additional tags after it.

Comment on lines +1 to +94
# HoloCat - EtherCAT Real-time Integration

![HoloCat Logo](docs/holocat_logo.png)

HoloCat is an EtherCAT master application that integrates the acontis EC-Master SDK with NVIDIA's Holoscan platform.

## Overview

HoloCat provides deterministic EtherCAT communication capabilities within the Holoscan ecosystem, enabling:

- **Real-time Control**
- **Holoscan Native**

## Prerequisites

### Required Dependencies

1. **acontis EC-Master SDK** (Commercial License)
- Version 3.2.3 or later

## Usage

### Prerequisites
```bash
# Set EC-Master SDK path
export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm

# Verify installation (optional)
./applications/holocat/scripts/verify_ecmaster.sh
```

### Build
```bash
# Build using HoloHub CLI (recommended)
./holohub build holocat --local
```

### Run
```bash
# Run with configuration file
./build/holocat/applications/holocat/cpp/holocat --config ./applications/holocat/configs/holocat_config.yaml
```

## Configuration

### Basic Configuration

Create `holocat_config.yaml`:

```yaml
holocat:
# Network adapter for EtherCAT
adapter_name: "eth0" # Change to your EtherCAT interface

# EtherCAT configuration file
eni_file: "/tmp/holocat_config.xml"

# Cycle time in microseconds
cycle_time_us: 1000 # 1ms cycle time

# Real-time priorities (1-99)
rt_priority: 39
job_thread_priority: 98

# Enable real-time scheduling
enable_rt: true

# Holoscan application configuration
holoscan:
logging:
level: "info"
```

### ENI File Generation

Use EtherCAT configuration tools to generate your ENI file.


## Troubleshooting

### Common Issues

1. **Permission Denied**
```bash
# Ensure capabilities are set
sudo setcap 'cap_net_raw=ep' ./build/holocat/applications/holocat/holocat
```

3. **EC-Master SDK Not Found**
```bash
# Verify ECMASTER_ROOT environment variable
echo $ECMASTER_ROOT
ls -la $ECMASTER_ROOT/SDK/INC/EcMaster.h
``` No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add architecture overview section.

Per coding guidelines, the README should include an architecture overview. Add a section explaining the operator architecture (HolocatOp, HcDataTxOp, HcDataRxOp) and how they interact with the EtherCAT master and Holoscan framework.

As per coding guidelines, README.md must include architecture overview.

🤖 Prompt for AI Agents
applications/holocat/README.md lines 1-94: The README lacks the required
"Architecture Overview" section; add a concise subsection titled "Architecture
Overview" describing the operator architecture: list and briefly describe
HolocatOp, HcDataTxOp, and HcDataRxOp, explain that HolocatOp manages lifecycle
and interfaces with the acontis EC‑Master SDK (initialization, ENI loading,
cycle scheduling), HcDataTxOp handles outgoing process data to EtherCAT slaves
and timing control, and HcDataRxOp handles incoming process data and publishes
to Holoscan; include a simple diagram or sequence description of how data flows
between Holoscan application -> HolocatOp -> (HcDataTxOp -> EtherCAT master ->
slaves) and (slaves -> EtherCAT master -> HcDataRxOp -> Holoscan), and mention
real‑time considerations (cycle timing and priorities) and configuration points
(adapter_name, eni_file, cycle_time_us).

Comment on lines +83 to +89
1. **Permission Denied**
```bash
# Ensure capabilities are set
sudo setcap 'cap_net_raw=ep' ./build/holocat/applications/holocat/holocat
```

3. **EC-Master SDK Not Found**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix troubleshooting section numbering.

The numbering jumps from issue 1 to issue 3, skipping 2.

Apply this diff:

-3. **EC-Master SDK Not Found**
+2. **EC-Master SDK Not Found**
🤖 Prompt for AI Agents
In applications/holocat/README.md around lines 83 to 89, the troubleshooting
list numbering skips from "1. Permission Denied" to "3. EC-Master SDK Not
Found"; update the ordered list so entries are sequential (1, 2, 3) by
renumbering the affected items or converting to an auto-numbered markdown list
so the second issue becomes "2. EC-Master SDK Not Found" (or use a continuous
numbered sequence) to restore correct ordering and consistency.

Comment on lines +111 to +118
for lib in "${LINK_LIBS[@]}"; do
if [ -f "$LIB_DIR/$lib" ]; then
print_status "OK" "$lib found"
((FOUND_LIBS++))
else
print_status "WARN" "$lib not found (may be optional)"
fi
done
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Arithmetic increment may cause premature exit with set -e.

When FOUND_LIBS is 0, the expression ((FOUND_LIBS++)) evaluates to 0 (falsy), which bash treats as a failure. Combined with set -e, this will exit the script prematurely on the first found library.

     if [ -f "$LIB_DIR/$lib" ]; then
         print_status "OK" "$lib found"
-        ((FOUND_LIBS++))
+        FOUND_LIBS=$((FOUND_LIBS + 1))
     else
         print_status "WARN" "$lib not found (may be optional)"
     fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for lib in "${LINK_LIBS[@]}"; do
if [ -f "$LIB_DIR/$lib" ]; then
print_status "OK" "$lib found"
((FOUND_LIBS++))
else
print_status "WARN" "$lib not found (may be optional)"
fi
done
for lib in "${LINK_LIBS[@]}"; do
if [ -f "$LIB_DIR/$lib" ]; then
print_status "OK" "$lib found"
FOUND_LIBS=$((FOUND_LIBS + 1))
else
print_status "WARN" "$lib not found (may be optional)"
fi
done
🤖 Prompt for AI Agents
In applications/holocat/scripts/verify_ecmaster.sh around lines 111-118, the use
of the post-increment expression ((FOUND_LIBS++)) can produce a zero exit status
when FOUND_LIBS is 0 and cause the script to exit under set -e; change the
increment to a form that yields a non-zero arithmetic result (for example use
FOUND_LIBS=$((FOUND_LIBS+1)) or ((FOUND_LIBS+=1))) so the operation does not
return a failing status and the loop won't prematurely exit.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Dec 9, 2025

Greptile Overview

Greptile Summary

This PR adds a new HoloCat application that integrates EtherCAT real-time industrial communication with the Holoscan streaming framework using the acontis EC-Master SDK. The application implements a three-operator pipeline architecture:

Architecture:

  • HcDataTxOp: Generates incrementing counter values (0-256) as test data
  • HolocatOp: Core EtherCAT master operator managing bus communication and state transitions
  • HcDataRxOp: Receives and processes data from the EtherCAT bus

Key Components:

  • Complete EtherCAT master lifecycle management (INIT → PREOP → SAFEOP → OP)
  • Asynchronous state machine for non-blocking transitions
  • Configurable cycle times and real-time priorities
  • Docker containerization with proper capabilities setup
  • Comprehensive build system integration with CMake
  • SDK verification tooling and documentation

Critical Issues Found:

  1. Dockerfile build failure: Undefined BASE_IMAGE variable (line 4)
  2. Buffer overflow vulnerability: strcpy without bounds checking in LogWrapper function (holocat_op.cpp:40)
  3. Race condition: stop() method doesn't wait for async state transition before deinitializing master (holocat_op.cpp:175-181)
  4. Configuration portability: Hardcoded developer paths in config files will break for other users

Architecture Quality:
The overall design follows good patterns with proper separation of concerns, configuration validation, and error handling. The integration with Holoscan's operator model is clean and the use of periodic conditions for real-time scheduling is appropriate.

Confidence Score: 2/5

  • This PR contains critical issues that will prevent successful build and runtime operation
  • Score reflects three critical issues: (1) Dockerfile build failure due to undefined BASE_IMAGE variable, (2) buffer overflow vulnerability in LogWrapper that could cause crashes, and (3) race condition in shutdown that could cause undefined behavior. Additionally, hardcoded paths make the application non-portable. These issues must be resolved before merging.
  • Dockerfile (won't build), holocat_op.cpp (buffer overflow and race condition), holocat_config.yaml (hardcoded paths)

Important Files Changed

File Analysis

Filename Score Overview
applications/holocat/Dockerfile 1/5 Docker build will fail due to undefined BASE_IMAGE variable
applications/holocat/cpp/holocat_op.cpp 2/5 Critical buffer overflow in LogWrapper, race condition in stop(), and unreachable code after throw
applications/holocat/CMakeLists.txt 4/5 Unreachable exit(1) after FATAL_ERROR (minor style issue)
applications/holocat/configs/holocat_config.yaml 2/5 Hardcoded developer-specific path will break for other users
applications/holocat/cpp/hc_data_tx_op.hpp 5/5 Minor typo in comment ('coutner' instead of 'counter')
applications/holocat/README.md 4/5 Documentation contains developer-specific paths in examples

Sequence Diagram

sequenceDiagram
    participant Main
    participant HolocatApp
    participant HcDataTxOp
    participant HolocatOp
    participant HcDataRxOp
    participant ECMaster as EC-Master SDK
    participant Bus as EtherCAT Bus

    Main->>HolocatApp: create & configure
    HolocatApp->>HolocatApp: extract_config()
    HolocatApp->>HolocatApp: validate_config()
    HolocatApp->>HcDataTxOp: create (100ms periodic)
    HolocatApp->>HolocatOp: create (cycle_time_us periodic)
    HolocatApp->>HcDataRxOp: create (on data available)
    HolocatApp->>HolocatApp: add_flow(TxOp→HolocatOp)
    HolocatApp->>HolocatApp: add_flow(HolocatOp→RxOp)
    
    Main->>HolocatApp: run()
    
    Note over HolocatOp,ECMaster: Startup Phase
    HolocatOp->>ECMaster: ecatInitMaster()
    ECMaster-->>HolocatOp: initialized
    
    loop State Machine Progression
        HolocatOp->>ECMaster: ConfigureNetwork()
        HolocatOp->>ECMaster: async ecatSetMasterState(INIT)
        HolocatOp->>ECMaster: async ecatSetMasterState(PREOP)
        HolocatOp->>ECMaster: async ecatSetMasterState(OP)
    end
    
    Note over HcDataTxOp,HcDataRxOp: Operational Phase
    
    loop Every 100ms
        HcDataTxOp->>HcDataTxOp: counter++ % 256
        HcDataTxOp->>HolocatOp: emit count_out
    end
    
    loop Every cycle_time_us
        HolocatOp->>ECMaster: ecatExecJob(ProcessAllRxFrames)
        ECMaster->>Bus: read process data
        Bus-->>ECMaster: input data
        ECMaster-->>HolocatOp: pbyPdIn
        
        HolocatOp->>HolocatOp: receive count_in
        HolocatOp->>HolocatOp: EC_COPYBITS to process output
        
        HolocatOp->>ECMaster: ecatExecJob(SendAllCycFrames)
        ECMaster->>Bus: write process data
        
        HolocatOp->>ECMaster: ecatExecJob(MasterTimer)
        HolocatOp->>ECMaster: ecatExecJob(SendAcycFrames)
        
        HolocatOp->>HcDataRxOp: emit count_out
        HcDataRxOp->>HcDataRxOp: process received count
    end
    
    Note over HolocatOp,ECMaster: Shutdown Phase
    Main->>HolocatOp: stop()
    HolocatOp->>ECMaster: async ecatSetMasterState(INIT)
    Note right of HolocatOp: Race condition: sleep(1) may not be enough
    HolocatOp->>ECMaster: ecatDeinitMaster()
    ECMaster-->>HolocatOp: deinitialized
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (2)

  1. applications/holocat/Dockerfile, line 3-4 (link)

    syntax: BASE_IMAGE is used but never defined. The ARG declares BASE_SDK_VERSION but the FROM uses ${BASE_IMAGE}. This will cause the Docker build to fail.

  2. applications/holocat/CMakeLists.txt, line 26-30 (link)

    syntax: Unreachable code. message(FATAL_ERROR ...) already terminates CMake execution, so exit(1) will never run.

19 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@bhashemian bhashemian requested a review from a team December 9, 2025 19:48
@bhashemian
Copy link
Member

Hi @hawkeyeking, thanks for this contribution. There are a few comments from the AI reviewer, which worth checking if not relevant please make the resolve with a short comment. Once they are addressed, we'd be happy to do the full review. Thaks

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (3)

  1. applications/holocat/CMakeLists.txt, line 26-29 (link)

    logic: Unreachable code - message(FATAL_ERROR ...) terminates CMake execution immediately, so exit(1) will never run.

  2. applications/holocat/Dockerfile, line 3-4 (link)

    syntax: BASE_IMAGE is used in the FROM directive but only BASE_SDK_VERSION is declared as an ARG. Either use the declared variable or add ARG BASE_IMAGE.

  3. applications/holocat/cpp/holocat_op.cpp, line 163-165 (link)

    logic: Unreachable code - return statement after throw will never execute.

19 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Copilot AI review requested due to automatic review settings December 18, 2025 16:21
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces HoloCat, a new application that integrates EtherCAT real-time industrial communication with NVIDIA's Holoscan SDK. It enables deterministic fieldbus communication for industrial automation applications using the commercial acontis EC-Master SDK.

Key Changes:

  • Complete EtherCAT master implementation with Holoscan operator architecture
  • Three operators: HolocatOp (main EtherCAT master), HcDataTxOp (data transmission), and HcDataRxOp (data reception)
  • Docker containerization with verification scripts and CMake build system

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
applications/holocat/metadata.json Application metadata with dependencies and configuration modes; category needs correction
applications/holocat/cpp/main.cpp Main entry point with CLI argument parsing; missing return statement
applications/holocat/cpp/holocat_op.{hpp,cpp} Core EtherCAT operator with state machine; unreachable code present
applications/holocat/cpp/holocat_app.{hpp,cpp} Application composition and config validation; format string inconsistency
applications/holocat/cpp/hc_data_tx_op.{hpp,cpp} Counter data generator operator; minor typo in comment
applications/holocat/cpp/hc_data_rx_op.{hpp,cpp} Data receiver operator; incorrect file header documentation
applications/holocat/cpp/CMakeLists.txt C++ build configuration with EC-Master SDK integration
applications/holocat/CMakeLists.txt Top-level build script; unreachable exit statement
applications/holocat/FindEcMaster.cmake CMake module for locating EC-Master SDK installation
applications/holocat/configs/holocat_config.yaml Runtime configuration; contains hardcoded developer-specific paths
applications/holocat/configs/eni2.xml EtherCAT Network Information configuration file
applications/holocat/scripts/verify_ecmaster.sh SDK verification utility; hardcoded path in example
applications/holocat/Dockerfile Container build definition; critical BASE_IMAGE variable issue
applications/holocat/README.md Documentation with setup and usage instructions; list numbering and hardcoded path issues
applications/CMakeLists.txt Adds holocat to build system

"aarch64"
],
"tags": [
"EtherCAT"
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The category "EtherCAT" is not in the approved category list. Based on the README description, this application provides "deterministic EtherCAT communication capabilities" for "Real-time Control" and appears to be focused on networking and industrial communication.

Please replace "EtherCAT" with an existing category from the approved category list. Here are some suitable alternatives:

  • For industrial real-time communication: Networking and Distributed Computing
  • For real-time control aspects: Robotics
  • For communication protocols: Interoperability

The most appropriate would be Networking and Distributed Computing or Interoperability given the EtherCAT protocol's focus on industrial networking.

Copilot generated this review using guidance from repository custom instructions.
holoscan::ExecutionContext& context) override;

private:
// coutner from 0 to maxcount for output on ECat bus
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "coutner" should be "counter".

Suggested change
// coutner from 0 to maxcount for output on ECat bus
// counter from 0 to maxcount for output on ECat bus

Copilot uses AI. Check for mistakes.
HOLOSCAN_LOG_ERROR("Cannot initialize EtherCAT-Master: {} (0x{:x})",
ecatGetText(dwRes), dwRes);
throw std::runtime_error("Cannot initialize EtherCAT-Master: " + std::string(ecatGetText(dwRes)));
return;
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreachable code: The return statement on line 165 will never be executed because line 164 throws an exception. Remove the return statement.

Suggested change
return;

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +9
adapter_name: "enxc84bd6d2788c"

# EtherCAT Network Information (ENI) file path
# Use environment variable HOLOCAT_ENI_FILE to override, or falls back to config dir
eni_file: "/home/hking/devel/holo/holohub/applications/holocat/configs/eni2.xml"
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded user-specific paths in configuration file. The adapter_name "enxc84bd6d2788c" and eni_file path "/home/hking/devel/holo/holohub/applications/holocat/configs/eni2.xml" contain developer-specific information that should be replaced with generic placeholders or relative paths. Consider using:

  • adapter_name: "eth0" (as shown in the README example)
  • eni_file: A relative path or environment variable-based path
Suggested change
adapter_name: "enxc84bd6d2788c"
# EtherCAT Network Information (ENI) file path
# Use environment variable HOLOCAT_ENI_FILE to override, or falls back to config dir
eni_file: "/home/hking/devel/holo/holohub/applications/holocat/configs/eni2.xml"
adapter_name: "eth0"
# EtherCAT Network Information (ENI) file path
# Use environment variable HOLOCAT_ENI_FILE to override, or falls back to config dir
eni_file: "eni2.xml"

Copilot uses AI. Check for mistakes.
### Prerequisites
```bash
# Set EC-Master SDK path
export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded user-specific path in documentation. The path "/home/hking/devel/ethercat/ecm" is developer-specific and should be replaced with a generic placeholder like "/path/to/ec-master" or "/opt/acontis/ecmaster".

Suggested change
export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm
export ECMASTER_ROOT=/opt/acontis/ecmaster # Adjust to your EC-Master install path

Copilot uses AI. Check for mistakes.
sudo setcap 'cap_net_raw=ep' ./build/holocat/applications/holocat/holocat
```

3. **EC-Master SDK Not Found**
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List numbering is incorrect. The list jumps from "1. Permission Denied" to "3. EC-Master SDK Not Found", skipping item 2. Either add the missing item 2 or renumber item 3 as item 2.

Suggested change
3. **EC-Master SDK Not Found**
2. **EC-Master SDK Not Found**

Copilot uses AI. Check for mistakes.
print_status "ERROR" "ECMASTER_ROOT environment variable not set"
echo " Set it to your EC-Master installation path:"
echo " export ECMASTER_ROOT=/path/to/ecm"
echo " Example: export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm"
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded user-specific path in example. Line 38 contains a developer-specific path "/home/hking/devel/ethercat/ecm" in the example that should use a generic placeholder path like "/path/to/ec-master" or "/opt/acontis/ecmaster".

Suggested change
echo " Example: export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm"
echo " Example: export ECMASTER_ROOT=/opt/acontis/ecmaster"

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +29

# Exit with failure
exit(1)
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exit(1) command on line 29 is unreachable because message(FATAL_ERROR) on line 26 already terminates the CMake configuration process. Remove lines 28-29 as they serve no purpose.

Suggested change
# Exit with failure
exit(1)

Copilot uses AI. Check for mistakes.
std::shared_ptr<HolocatOp> holocat_op = make_operator<HolocatOp>("holocat_op", ecat_bus_periodic_cond);
holocat_op->set_config(config);
add_operator(holocat_op);
HOLOSCAN_LOG_INFO("HoloCat operator created with %dus periodic condition", config.cycle_time_us);
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent log formatting. Line 39 uses printf-style format string "%dus" while other log statements in the same function (lines 30, 31) use modern C++ format string style with "{}". Use the consistent format string style: HOLOSCAN_LOG_INFO("HoloCat operator created with {}us periodic condition", config.cycle_time_us);

Suggested change
HOLOSCAN_LOG_INFO("HoloCat operator created with %dus periodic condition", config.cycle_time_us);
HOLOSCAN_LOG_INFO("HoloCat operator created with {}us periodic condition", config.cycle_time_us);

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +32
usermod -aG sudo holocat && \
echo "holocat ALL=(ALL) NOPASSWD: /usr/sbin/setcap" >> /etc/sudoers

Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Dockerfile grants the holocat user passwordless sudo access to /usr/sbin/setcap, which allows that user (and any code running as it) to assign arbitrary Linux capabilities to any binary in the container. If an attacker gains code execution as holocat, they can use sudo setcap to escalate privileges and grant powerful capabilities (e.g., raw network, sys_admin) to other binaries, breaking the intended least-privilege isolation. Consider removing this sudoers entry and instead setting the minimal required capabilities at build time or via the container runtime, without allowing arbitrary setcap invocation from inside the container.

Suggested change
usermod -aG sudo holocat && \
echo "holocat ALL=(ALL) NOPASSWD: /usr/sbin/setcap" >> /etc/sudoers
usermod -aG sudo holocat

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (9)

  1. applications/CMakeLists.txt, line 152 (link)

    style: The holocat application should be placed in alphabetical order per the comment on line 16. It should be positioned between 'high_speed_endoscopy' and 'holochat'.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  2. applications/holocat/CMakeLists.txt, line 28-29 (link)

    logic: unreachable code after FATAL_ERROR - CMake stops processing after the fatal error message

  3. applications/holocat/cpp/hc_data_tx_op.hpp, line 53 (link)

    syntax: Typo: 'coutner' should be 'counter'

  4. applications/holocat/cpp/holocat_op.cpp, line 165 (link)

    syntax: unreachable code after throw statement

  5. applications/holocat/cpp/hc_data_rx_op.hpp, line 42 (link)

    style: Documentation inconsistency - comment states op_input is unused but this is a receiver operator, not a source operator

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  6. applications/holocat/Dockerfile, line 4 (link)

    logic: BASE_IMAGE variable is undefined. Change to BASE_SDK_VERSION or add ARG BASE_IMAGE declaration.

  7. applications/holocat/metadata.json, line 5-7 (link)

    style: missing author name field - only affiliation is specified. Should an author name be added to the metadata?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  8. applications/holocat/cpp/holocat_app.cpp, line 42-43 (link)

    style: Condition name 'ethercat_cycle' is used for both EtherCAT bus and counter update conditions, but they have different periods (configurable vs 100ms). Consider using distinct names. Should these conditions have the same name when they serve different purposes with different timing?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  9. applications/holocat/cpp/hc_data_rx_op.cpp, line 5-6 (link)

    syntax: Comment incorrectly describes HcDataTxOp instead of HcDataRxOp

19 files reviewed, 9 comments

Edit Code Review Agent Settings | Greptile

@bhashemian
Copy link
Member

Hi @hawkeyeking, it would be great if you could address the comments on this PR. Please don’t hesitate to reach out if you need any help. Thanks!

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 files reviewed, 8 comments

Edit Code Review Agent Settings | Greptile

# HoloCat EtherCAT Application Dockerfile

ARG BASE_SDK_VERSION
FROM ${BASE_IMAGE}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the variable BASE_IMAGE is undefined and will cause Docker build failure. The ARG BASE_SDK_VERSION is declared on line 3 but never used.

Suggested change
FROM ${BASE_IMAGE}
FROM nvcr.io/nvidia/clara-holoscan/holoscan:${BASE_SDK_VERSION}

Comment on lines +38 to +41
char buffer[1024];
const char* prefix = "[EC-Master] ";
strcpy(buffer, prefix);
vsnprintf(buffer + strlen(prefix), sizeof(buffer) - strlen(prefix), szFormat, vaArgs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buffer overflow vulnerability: strcpy does not perform bounds checking. If prefix length + formatted string length exceeds 1024 bytes, this will write beyond buffer bounds causing memory corruption.

Suggested change
char buffer[1024];
const char* prefix = "[EC-Master] ";
strcpy(buffer, prefix);
vsnprintf(buffer + strlen(prefix), sizeof(buffer) - strlen(prefix), szFormat, vaArgs);
char buffer[1024];
const char* prefix = "[EC-Master] ";
size_t prefix_len = strlen(prefix);
strncpy(buffer, prefix, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
vsnprintf(buffer + prefix_len, sizeof(buffer) - prefix_len - 1, szFormat, vaArgs);

Comment on lines +164 to +165
throw std::runtime_error("Cannot initialize EtherCAT-Master: " + std::string(ecatGetText(dwRes)));
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the return statement after throw is unreachable code and should be removed

Suggested change
throw std::runtime_error("Cannot initialize EtherCAT-Master: " + std::string(ecatGetText(dwRes)));
return;
throw std::runtime_error("Cannot initialize EtherCAT-Master: " + std::string(ecatGetText(dwRes)));

Comment on lines +26 to +29
message(FATAL_ERROR "EC-Master SDK not found")

# Exit with failure
exit(1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exit(1) after FATAL_ERROR is unreachable. CMake's message(FATAL_ERROR ...) immediately terminates configuration, so the exit(1) call will never execute.

Suggested change
message(FATAL_ERROR "EC-Master SDK not found")
# Exit with failure
exit(1)
message(FATAL_ERROR "EC-Master SDK not found")


# EtherCAT Network Information (ENI) file path
# Use environment variable HOLOCAT_ENI_FILE to override, or falls back to config dir
eni_file: "/home/hking/devel/holo/holohub/applications/holocat/configs/eni2.xml"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardcoded developer-specific absolute path /home/hking/... will fail for other users. Use a relative path or environment variable instead.

Suggested change
eni_file: "/home/hking/devel/holo/holohub/applications/holocat/configs/eni2.xml"
eni_file: "${HOLOCAT_CONFIG_DIR}/eni2.xml"

Comment on lines +175 to +181
pending_state_transition_ = std::async(std::launch::async, [this]() {
return ecatSetMasterState(kEthercatStateChangeTimeout_, eEcatState_INIT);
});

sleep(1);
// deinitialize master
ecatDeinitMaster();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

race condition: the async state transition is launched but there's only a 1-second sleep() before calling ecatDeinitMaster(). If the state transition takes longer than 1 second, ecatDeinitMaster() will be called while the async operation is still accessing the master, potentially causing a crash or undefined behavior. Should wait for the future to complete before deinitializing.

Suggested change
pending_state_transition_ = std::async(std::launch::async, [this]() {
return ecatSetMasterState(kEthercatStateChangeTimeout_, eEcatState_INIT);
});
sleep(1);
// deinitialize master
ecatDeinitMaster();
HOLOSCAN_LOG_INFO("HolocatOp: stopping EtherCAT Master");
// reset master to INIT
pending_state_transition_ = std::async(std::launch::async, [this]() {
return ecatSetMasterState(kEthercatStateChangeTimeout_, eEcatState_INIT);
});
// Wait for state transition to complete before deinitializing
if (pending_state_transition_.valid()) {
pending_state_transition_.wait();
}
// deinitialize master
ecatDeinitMaster();

holoscan::ExecutionContext& context) override;

private:
// coutner from 0 to maxcount for output on ECat bus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'coutner' is mis-spelled

Suggested change
// coutner from 0 to maxcount for output on ECat bus
// counter from 0 to maxcount for output on ECat bus

### Prerequisites
```bash
# Set EC-Master SDK path
export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardcoded developer-specific path /home/hking/... in example documentation. Should use a generic placeholder path.

Suggested change
export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm
export ECMASTER_ROOT=/path/to/ecmaster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants